package com.happyface.andquiz.internals;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Class used to map a question
 * 
 * @author Theo
 * 
 */
public class Question {
    private String questionText;
    private String optionA;
    private String optionB;
    private String optionC;
    private String optionD;
    private int[] optionsRemoved;
    private Random randomGenerator;

    /**
     * Create a Question object
     * 
     * @param questionText
     *            the text of the question
     * @param optionA
     *            option A answer
     * @param optionB
     *            option B answer
     * @param optionC
     *            option C answer *
     * @param optionD
     *            option D answer
     */
    public Question(String questionText, String optionA, String optionB,
	    String optionC, String optionD) {
	if (questionText == null) {
	    throw new IllegalArgumentException(
		    "Argument 'questionText' cannot be null");
	}
	if (optionA == null) {
	    throw new IllegalArgumentException(
		    "Argument 'optionA' cannot be null");
	}
	if (optionB == null) {
	    throw new IllegalArgumentException(
		    "Argument 'optionB' cannot be null");
	}
	if (optionC == null) {
	    throw new IllegalArgumentException(
		    "Argument 'optionC' cannot be null");
	}
	if (optionD == null) {
	    throw new IllegalArgumentException(
		    "Argument 'optionD' cannot be null");
	}

	this.randomGenerator = new Random();
	this.optionsRemoved = new int[4];

	this.questionText = questionText;
	this.optionA = optionA;
	this.optionB = optionB;
	this.optionC = optionC;
	this.optionD = optionD;
    }

    /**
     * Gets the text of the question
     * 
     * @return the text
     */
    public String getQuestionText() {
	return this.questionText;
    }

    /**
     * Gets the option A possible answer
     * 
     * @return
     */
    public String getOptionA() {
	if (this.optionA.charAt(0) == '*') {
	    return this.optionA.substring(1);
	} else {
	    return this.optionA;
	}
    }

    /**
     * Gets the option D possible answer
     * 
     * @return
     */
    public String getOptionB() {
	if (this.optionB.charAt(0) == '*') {
	    return this.optionB.substring(1);
	} else {
	    return this.optionB;
	}
    }

    /**
     * Gets the option C possible answer
     * 
     * @return
     */
    public String getOptionC() {
	if (this.optionC.charAt(0) == '*') {
	    return this.optionC.substring(1);
	} else {
	    return this.optionC;
	}
    }

    /**
     * Gets the option D possible answer
     * 
     * @return
     */
    public String getOptionD() {
	if (this.optionD.charAt(0) == '*') {
	    return this.optionD.substring(1);
	} else {
	    return this.optionD;
	}
    }

    /**
     * Gets the answer to the question
     * 
     * @return the answer, null if no answer
     */
    public String getCorrectAnswer() {
	if (this.optionA.charAt(0) == '*') {
	    return this.optionA.substring(1);
	} else if (this.optionB.charAt(0) == '*') {
	    return this.optionB.substring(1);
	} else if (this.optionC.charAt(0) == '*') {
	    return this.optionC.substring(1);
	} else if (this.optionD.charAt(0) == '*') {
	    return this.optionD.substring(1);
	} else
	    return null;
    }

    /**
     * Gets one of the wrong answers to the question
     * 
     * @return the wrong answer
     */
    public String getWrongAnswer() {
	int randomNumber = 0;

	while (true) {
	    randomNumber = (int) (4 * randomGenerator.nextDouble());
	    switch (randomNumber) {
	    case 0:
		if (this.optionA.charAt(0) != '*') {
		    return this.getOptionA();
		}
		break;
	    case 1:
		if (this.optionB.charAt(0) != '*') {
		    return this.getOptionB();
		}
		break;
	    case 2:
		if (this.optionC.charAt(0) != '*') {
		    return this.getOptionC();
		}
		break;
	    case 3:
		if (this.optionD.charAt(0) != '*') {
		    return this.getOptionD();
		}
		break;
	    default:
		break;
	    }
	}
    }

    /**
     * Gets a wrong answer to be removed from the possible options
     * 
     * @return the wrong answer
     */
    public String do25Percent() {

	int randomNumber = 0;

	while (true) {
	    randomNumber = (int) (4 * randomGenerator.nextDouble());
	    switch (randomNumber) {
	    case 0:
		if (this.optionA.charAt(0) != '*' && optionsRemoved[0] != 1) {
		    optionsRemoved[0] = 1;
		    return this.getOptionA();
		}
		break;
	    case 1:
		if (this.optionB.charAt(0) != '*' && optionsRemoved[1] != 1) {
		    optionsRemoved[1] = 1;
		    return this.getOptionB();
		}
		break;
	    case 2:
		if (this.optionC.charAt(0) != '*' && optionsRemoved[2] != 1) {
		    optionsRemoved[2] = 1;
		    return this.getOptionC();
		}
		break;
	    case 3:
		if (this.optionD.charAt(0) != '*' && optionsRemoved[3] != 1) {
		    optionsRemoved[3] = 1;
		    return this.getOptionD();
		}
		break;
	    default:
		break;
	    }
	}
    }

    /**
     * Gets an answer from the specialist
     * 
     * @param rateOfSuccess
     *            the chance the specialist will answer correct
     * @return the specialist's answer
     */
    public String askTheSpecialist(int rateOfSuccess) {
	Answer correctAnswer = new Answer(true, rateOfSuccess);
	Answer wrongAnswer = new Answer(false, 100 - rateOfSuccess);
	// build list to choose from
	List<Answer> chooseFrom = new ArrayList<Question.Answer>();
	chooseFrom.add(correctAnswer);
	chooseFrom.add(wrongAnswer);

	int cumulative = 0;
	int randomNumber = (int) (100 * randomGenerator.nextDouble());
	String answer = null;

	for (Answer answ : chooseFrom) {
	    cumulative += answ.getWeight();
	    if (randomNumber < cumulative) {
		if (answ.isCorrect()) {
		    answer = this.getCorrectAnswer();
		    break;
		} else {
		    answer = this.getWrongAnswer();
		    break;
		}
	    }
	}

	return answer;
    }

    private class Answer {
	private boolean correct;
	private int weight;

	public Answer(boolean correct, int weight) {
	    this.correct = correct;
	    this.weight = weight;
	}

	public boolean isCorrect() {
	    return correct;
	}

	public int getWeight() {
	    return weight;
	}
    }
}
